import static org.junit.Assert.*;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class Runner {
	private final static int MAX_NUMBER = 1024 * 1024;
	private final static int CYCLES = 1024 * 64;
	private final static int INTERNAL_CYCLES = 16;

	protected static Factorizator factorizator;
	protected static ExecutorService executor;

	public void initFactorizator() {
		int[] primes = DKUtil.makeIntArray(DKUtil.generatePrimes(MAX_NUMBER));
		factorizator = new Factorizator(primes);
	}

	public Runnable newTask() {
		return new Runnable() {
			public void run() {
				for (int i = 0; i < INTERNAL_CYCLES; i++) {
					factorizator.factorize((int) (2 + Math.random()
							* (MAX_NUMBER - 1)));
				}
			}
		};
	}

	@Before
	public void initExecutor() {
		executor = Executors.newFixedThreadPool(32);
	}

	@After
	public void checkResults() throws InterruptedException {
		waitFor();
		assertEquals(CYCLES * INTERNAL_CYCLES, factorizator.getCount());
	}

	@Test
	public void test() {
		initFactorizator();
		for (int i = 0; i < CYCLES; i++) {
			executor.submit(newTask());
		}
	}

	protected void waitFor() throws InterruptedException {
		executor.shutdown();
		boolean terminated = executor.awaitTermination(Long.MAX_VALUE,
				TimeUnit.SECONDS);
		assertTrue("Finished all tasks.", terminated);
	}
}
